import config from '@/settings'
import request from '@/utils/request'
import { pagerMixin } from '@/mixins'
import { isFunction } from '@/utils/types'
import './index.scss'
import { FormBox } from '../Form'
import { isEmpty } from '@/utils/util'

const getFilterData = (fields) => {
  const filterData = {}
  const list = isFunction(fields) ? fields() : fields
  list.map(x => {
    if (x.initialValue != null) {
      if (x.type === 'daterange') {
        filterData[x.key1] = x.initialValue[0]
        filterData[x.key2] = x.initialValue[1]
      } else {
        filterData[x.key] = x.initialValue
      }
    }
  })
  return filterData
}

export default {
  name: 'STable',
  components: {
    FormBox
  },
  mixins: [pagerMixin],
  data () {
    return {
      filterData: Object.assign({}, this.filterDataProps), // 删选条件

      localTableData: [],
      localSort: null, // 排序条件
      localLoading: false,
      localPagination: Object.assign({}, this.pagination),

      selectedRows: [],
      selectedRowKeys: [],

      renderFilterFlag: true,
      renderTableFlag: true,
      renderFlag: true,

      tableHeight: '100%'
    }
  },
  props: {
    title: {
      type: String,
      default: ''
    },
    dataPops: {
      type: Array,
      default: () => {
        return []
      }
    },
    rowKey: {
      type: [String, Function],
      default: 'id'
    },
    pageNum: {
      type: Number,
      default: 1
    },
    pageSize: {
      type: Number,
      default: config.pageSize
    },
    // 请求地址
    reqUrl: {
      type: String,
      default: ''
    },
    // 请求方式
    reqMethod: {
      type: String,
      default: 'POST'
    },
    queryFn: {
      type: Function,
      default: null
    },
    alert: {
      type: [Object, Boolean],
      default: null
    },
    column: {
      type: Array,
      default: () => []
    },
    filterProps: {
      type: Object,
      default: () => null
    },
    showSizeChanger: {
      type: Boolean,
      default: false
    },
    dataKey: {
      type: String,
      default: 'content'
    },
    pagination: {
      type: Object,
      default: () => {
        return {}
      }
    },
    loading: {
      type: Boolean,
      default: false
    },
    callback: {
      type: Function,
      default: null
    },
    // 携带筛选参数，可更改
    filterDataProps: {
      type: Object,
      default: () => {}
    },
    // 需要固定携带的请求参数
    queryPropsParams: {
      type: Object,
      default: () => {}
    },
    // 是否初始化请求参数（主要在路由返回需要展示上次数据）
    initParameter: {
      type: Boolean,
      default: false
    },
    border: { // 是否显示竖直方向的边线
      type: Boolean,
      default: false
    }
  },
  computed: {
    isSyncReq () {
      return !!this.queryFn || !!this.reqUrl
    },
    tableAttrs () {
      return Object.assign({}, {
        'row-key': this.rowKey,
        size: 'large',
        border: this.border
      }, this.$attrs)
    }
  },
  watch: {
    pageNum (val) {
      Object.assign(this.localPagination, {
        'current-page': val
      })
    },
    pageSize (val) {
      Object.assign(this.localPagination, {
        pageSize: val
      })
    },
    showSizeChanger (val) {
      Object.assign(this.localPagination, {
        showSizeChanger: val
      })
    },
    filterDataProps (val) {
      this.filterData = Object.assign({}, val)
    },
    filterProps: {
      handler (val) {
        if (val && val.watch) {
          this.filterData = getFilterData(val.fields)
        }
      }
    },
    // 重新计算表格列表
    dataPops: {
      handler (val) {
        const { pageSize, isSyncReq, pagination } = this
        if (Array.isArray(val) && !isSyncReq) {
          this.localTableData = val.filter((x, index) => {
            return !pagination || index < pageSize
          })
        }
      },
      deep: true,
      immediate: true
    }
  },
  created () {
    // 获取初始删选条件
    if (this.filterProps && this.filterProps.fields) {
      this.filterData = getFilterData(this.filterProps.fields)
    }
    let { pageNo } = this.$route.params
    if (this.initParameter && !pageNo) {
      pageNo = (this.pageParameter.pageNum || 0) + 1
    }
    const localPageNum = (pageNo && parseInt(pageNo)) || this.pageNum
    this.localPagination = this.pagination ? Object.assign({}, this.localPagination, {
      'current-page': localPageNum,
      // 'hide-on-single-page': true,
      pageSize: this.pageSize
    }) : false
    if (this.isSyncReq) {
      // 判断自主加载数据
      this.loadData()
    }
  },
  methods: {
    /**
     * 表格重新加载方法
     * 如果参数为 true, 则强制刷新到第一页
     * @param Boolean bool
     */
    refresh (bool = false) {
      bool && (this.localPagination = Object.assign({}, {
        'current-page': 1,
        pageSize: this.localPagination.pageSize || this.pageSize
      }))
      this.loadData()
    },
    // 重新加载表格
    reloadTable () {
      const that = this
      this.renderTableFlag = false
      this.refresh(true)
      this.$nextTick(function () {
        that.renderTableFlag = true
      })
    },
    // 重新加载删选表单
    reloadFilter () {
      this.renderFilterFlag = false
      this.refresh(true)
      this.$nextTick(function () {
        this.renderFilterFlag = true
      })
    },
    curPaginationChange (val) {
      console.log(`curPaginationChange:${val}`)
      if (val > 100) {
        this.$message.warning('数据较大，请通过搜索条件控制范围！')
      }
      this.loadData({ pageNum: val > 100 ? 100 : val })
    },
    // 每页条数改变
    curPaginationSizeChange (val) {
      this.localPagination.pageSize = val
      this.loadData({ pageSize: val })
    },
    sortChange (e) {
      let values = {}
      if (e.order) {
        values = {
          orderField: e.prop,
          orderType: e.order === 'ascending' ? 'asc' : 'desc'
        }
        this.localSort = values
      }
      this.loadData()
    },
    // 当用户对某一行展开或者关闭的时候会触发该事件
    expandChange (row, expandedRows) {
      const { tableAttrs } = this
      if (Array.isArray(expandedRows)) {
        try {
          const keys = expandedRows.map(x => { return x[tableAttrs['row-key']] })
          // 判断展开或关闭
          if (keys.includes(row[tableAttrs['row-key']])) {
            this.$emit('expandRow', row)
          }
        } catch (err) {
          console.log(err)
        }
      }
    },
    searchSubmit (e) {
      if (this.isSyncReq) {
        this.filterData = { ...e }
        this.loadData({ ...this.localPagination, pageNum: 1 })
      } else {
        this.$emit('filterHandle', e)
      }
    },
    exportHandle () {
      return this.filterData
    },
    reload () {
      this.renderFlag = false
      this.filterData = null
      this.localSort = null
      this.refresh(true)
      this.$nextTick(function () {
        this.renderFlag = true
      })
    },
    /**
    * 加载数据方法
    * @param {Object} pagination 分页选项器
    */
    loadData (pagination) {
      const { isSyncReq, queryFn, reqUrl, reqMethod, pageSize, dataPops } = this
      if (!isSyncReq) {
        const { pageNum = 1 } = pagination || {}
        if (Array.isArray(dataPops)) {
          this.localTableData = dataPops.filter((x, index) => {
            return index < pageSize * pageNum && index >= pageSize * (pageNum - 1)
          })
        }
        return
      }
      const filterData = {}
      Object.keys(this.filterData).forEach(x => {
        if (!isEmpty(this.filterData[x])) {
          filterData[x] = this.filterData[x]
        }
      })
      this.localLoading = true
      // 合并axios参数，包括页码，页数，排序，过滤和筛选表单值
      const parameter = {
        ...this.queryPropsParams,
        ...filterData,
        pageNum: ((pagination && pagination.pageNum) || this.localPagination['current-page']) - 1,
        pageSize: (pagination && pagination.pageSize) || this.localPagination.pageSize,
        ...this.localSort
      }
      let fn = null
      if (queryFn) {
        fn = queryFn(parameter)
      } else {
        fn = request({
          url: reqUrl,
          method: reqMethod,
          params: parameter
        })
      }

      fn.then(res => {
        if (this.callback && this.callback({ res, parameter })) res = this.callback({ res, parameter })
        this.localTableData = res && Array.isArray(res) ? res : res[this.dataKey] || []
        this.localPagination = Object.assign({}, this.localPagination, {
          total: (res.totalElements && typeof res.totalElements === 'number') ? res.totalElements : this.localTableData.length,
          'current-page': (parseInt(res.number ?? 0)) + 1,
          pageSize: parameter.pageSize
        })
        console.log(this.localPagination)
      }).catch(err => {
        console.log(err)
        this.localTableData = []
        this.localPagination = {
          total: 0,
          'current-page': 1,
          pageSize: parameter.pageSize
        }
      }).finally(() => {
        this.localLoading = false
      })
    }
  },
  render (h) {
    // const _this = this
    const { localPagination, isSyncReq, localTableData, localLoading, renderFilterFlag, renderTableFlag, renderFlag, tableAttrs } = this
    const { column, pagination, dataPops, filterProps, loading, rowKey } = this.$props
    const $scopedSlots = this.$scopedSlots
    const table = (
      <div class={`tableContent ${tableAttrs.size}`}>
        <el-table
          ref='table'
          rowKey={rowKey}
          v-loading={isSyncReq ? localLoading : loading}
          element-loading-text='加载中.'
          element-loading-background='rgba(255, 255, 255, 0.7)'
          element-loading-customClass='v-loading'
          element-loading-spinner='iconfont icon-weibiaoti-3'
          // cell-style={{padding: '6px 0'}}
          data={localTableData}
          span-method={tableAttrs.spanMethod}
          {...{ props: tableAttrs, scopedSlots: { ...this.$scopedSlots }, on: { ...this.$listeners }}}
        >
          {tableAttrs.selection &&
            <el-table-column type='selection' width='48px' fixed='left' selectable={tableAttrs.selectable} reserve-selection={true}></el-table-column>
          }
          {column.map(item => {
            return h('el-table-column', {
              props: {
                prop: item.prop,
                label: item.label,
                width: item.width ? item.width : item.prop === 'sort' ? '64' : 'auto',
                'show-overflow-tooltip': !item.tooltip,
                // 'header-align': 'center',
                align: item.align || 'center',
                fixed: item.prop === 'sort' ? 'left' : item.prop === 'action' ? 'right' : false,
                ...item.rest
              },
              scopedSlots: {
                default: scope => {
                  const value = scope.row[item.prop]
                  if (item.type && item.type === 'img') {
                    return h('img', {
                      style: {
                        width: '60px',
                        height: '60px'
                      },
                      attrs: {
                        src: `${value}`
                      }
                    }, scope.$index + 1)
                  } else if ($scopedSlots[item.prop]) {
                    return h('span', {
                      // slot: 'date',
                      class: {
                        'actionCell': item.prop === 'action'
                      }
                    }, $scopedSlots[item.prop](value, scope.row, scope.$index))
                  } else if (item.prop === 'sort') {
                    return h('span', {}, scope.$index + 1)
                  } else if (item.render) {
                    return h('span', {}, item.render(scope.row))
                  } else {
                    return h('span', {}, value || value === 0 ? value : '--')
                  }
                }
              }
            })
          })}
        </el-table>
        {!!pagination &&
          <el-pagination
            class='tablePagination tr'
            hide-on-single-page={!isSyncReq}
            style={{ flex: '1 0 1' }}
            page-size={localPagination.pageSize}
            {...{
              props: isSyncReq ? localPagination : {
                ...localPagination,
                total: dataPops.length
              }
            }}
            prev-text='上一页'
            next-text='下一页'
            page-sizes={[5, 10, 20, 30, 40, 50, 100]}
            layout={localPagination.layout || 'slot, prev, pager, next, jumper'}
            onCurrent-change={this.curPaginationChange}
            onSize-change={this.curPaginationSizeChange}
          />
        }
      </div>
    )

    return (
      renderFlag && <div class='tableWrapper'>
        {filterProps && renderFilterFlag &&
          <div class='tableFilter' id='tableFilter'>
            {$scopedSlots['filter-left'] && $scopedSlots['filter-left']()}
            {filterProps.fields &&
              <form-box
                layoutCol={{ sm: 12, md: 8, lg: 6 }}
                {...{ props: filterProps }}
                isFilter={true}
                style='flex: 1'
                submitHandle={this.searchSubmit}
              />
            }
            {$scopedSlots['table-operator'] && $scopedSlots['table-operator']()}
          </div>
        }
        <div class='tableBox' shadow='never'>
          {$scopedSlots['table-switch'] && $scopedSlots['table-switch']()}
          {renderTableFlag && table}
          {$scopedSlots.sumBox && $scopedSlots.sumBox()}
        </div>
      </div>
    )
  }
}
